﻿using System;
using System.Net.Http;
using System.Threading.Tasks;
using Linker.TaskCenter.Helpers;
using Linker.TaskCenter.Http;
using Linker.TaskCenter.Services;
using Linker.TaskCenter.Tasks.Entity;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.Domain.Services;

namespace Linker.TaskCenter.Tasks
{
    public class TaskManager : DomainService, ITaskManager
    {
        private readonly ILogger<TaskWorker> _logger;
        private readonly CSRedisHelper _redisHelper;
        private readonly IRepository<TaskEntity, Guid> _repository;
        private readonly IRepository<ServiceEntity, Guid> _serviceRepository;

        public TaskManager(IRepository<TaskEntity, Guid> repository,
            IRepository<ServiceEntity, Guid> serviceRepository,
            ILogger<TaskWorker> logger,
            CSRedisHelper redisHelper)
        {
            _repository = repository;
            _serviceRepository = serviceRepository;
            _redisHelper = redisHelper;
            _logger = logger;
        }

        public async Task ExecuteTaskAsync(RequestMessageData task)
        {
            var id = task.TaskId;
            var url = task.Url;
            var parameters = task.Parameters;

            const int SuccessCode = 0;
            var entity = await _repository.GetAsync(id);
            if (entity == null)
            {
                _logger.LogError($"the task id {id} is not exits");
                return;
            }

            var service = await _serviceRepository.GetAsync(entity.ServiceId);
            if (service != null && service.Status != ServiceHealthyEnum.Healthy)
            {
                _logger.LogError($"The Server {service.ServerName} is {service.Status}");
                // 服务状态不健康，入重试队列
                await _redisHelper.PushAsync(AppConsts.RetryTaskQueueKey, task);
                return;
            }

            // Execute
            entity.ResponseResult = TaskResponseResultEnum.Error;
            try
            {
                var client = new HttpClient();
                var response = await client.PostAsync(new Uri(url), new JsonContent(parameters));
                var content = await response.Content.ReadAsStringAsync();
                _logger.LogInformation($"Post url {url}, response: {content} ");

                entity.Response = content;
                if (response.IsSuccessStatusCode)
                {
                    var obj = JsonConvert.DeserializeObject<ServerHttpResponse>(content);
                    if (obj?.Code == SuccessCode)
                    {
                        entity.ResponseResult = TaskResponseResultEnum.Success;
                        // Callback Url
                        if (!string.IsNullOrEmpty(entity.CallbackUrl))
                        {
                            entity.CallbackResult = await Callback(entity.CallbackUrl);
                        }
                    }
                    else
                    {
                        entity.Error = obj?.Message;
                    }
                }
            }
            catch (Exception e)
            {
                entity.Error = e.Message;
                _logger.LogError($"Post url {url}, parameters:{parameters}, error: {e.Message} ");
            }

            entity.Status = TaskStatusEnum.Done;
            await _repository.UpdateAsync(entity);
        }

        private async Task<string> Callback(string url)
        {
            try
            {
                var client = new HttpClient();
                var response = await client.GetAsync(url);
                var str = await response.Content.ReadAsStringAsync();
                return str;
            }
            catch (Exception e)
            {
                _logger.LogError($"Callback url {url}, error: {e.Message} ");
                return e.Message;
            }
        }
    }
}